package com.mofum.msdom.excel.utils;

import com.mofum.msdom.excel.collections.*;
import com.mofum.msdom.excel.converter.ExcelConverter;
import com.mofum.msdom.excel.converter.TypeConverter;
import com.mofum.msdom.excel.converter.impl.excel.StringExcelConvert;
import com.mofum.msdom.excel.converter.impl.javatype.StringConvert;
import com.mofum.msdom.excel.filter.DataFilter;
import com.mofum.msdom.excel.metadata.MPColumn;
import com.mofum.msdom.excel.metadata.MPSheet;
import com.mofum.msdom.excel.validator.Validator;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * 列转换工具类
 *
 * @author 1615690513@qq.com
 * @since 2018/11/22 0022 19:18
 */
public class MetadataConvertUtils {

    /**
     * Map映射关系转字段Map
     *
     * @param dataType  数据类型
     * @param columnMap Map映射关系
     * @param <T>       类型
     *                  字段Map
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> FieldMPColumnMap convertStringToColumn(Class<T> dataType, Map<String, Integer> columnMap) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        FieldMPColumnMap fieldMPColumnMap = new FieldMPColumnMap();
        for (String key : columnMap.keySet()) {
            Field field = dataType.getDeclaredField(key);
            if (field == null) {
                continue;
            }
            MPColumn mpColumn = new MPColumn();
            mpColumn.setIndex(columnMap.get(key));
            fieldMPColumnMap.put(field, mpColumn);
        }
        return fieldMPColumnMap;
    }

    /**
     * 字段列Map转转换器Map
     *
     * @param columnMap 字段列Map
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Map<Field, TypeConverter> columnMapToConverterMap(Map<Field, MPColumn> columnMap, Class<? extends TypeConverter> defaultConvert) throws IllegalAccessException, InstantiationException {

        Map<Field, TypeConverter> converterMap = new HashMap<Field, TypeConverter>();

        for (Field field : columnMap.keySet()) {

            MPColumn mpColumn = columnMap.get(field);

            if (mpColumn.getConverter().equals(TypeConverter.class) || mpColumn.getConverter() == null) {
                mpColumn.setConverter(defaultConvert);
            }

            converterMap.put(field, mpColumn.getConverter().newInstance());

        }

        return converterMap;

    }

    /**
     * 工作表Map验证器Map
     *
     * @param sheetMap 工作表Map
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Map<Integer, DataFilter[]> sheetMapToDataFilterMap(Map<Integer, MPSheet> sheetMap) throws IllegalAccessException, InstantiationException {

        Map<Integer, DataFilter[]> dataFilterMap = new HashMap<Integer, DataFilter[]>();

        for (Integer sheetIndex : sheetMap.keySet()) {

            MPSheet mpSheet = sheetMap.get(sheetIndex);

            if (mpSheet.getFilters() == null) {
                continue;
            }

            int length = mpSheet.getFilters().length;

            if (length <= 0) {
                continue;
            }

            DataFilter[] filters = new DataFilter[length];

            for (int i = 0; i < length; i++) {
                filters[i] = mpSheet.getFilters()[i].newInstance();
            }
            dataFilterMap.put(sheetIndex, filters);
        }

        return dataFilterMap;

    }

    /**
     * 字段列Map验证器Map
     *
     * @param columnMap 字段列Map
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static Map<Field, Validator> columnMapToValidatorMap(Map<Field, MPColumn> columnMap, Class<? extends Validator> defaultValidator) throws IllegalAccessException, InstantiationException {

        Map<Field, Validator> validatorMap = new HashMap<Field, Validator>();

        for (Field field : columnMap.keySet()) {

            MPColumn mpColumn = columnMap.get(field);

            if (mpColumn.getValidator().equals(Validator.class) || mpColumn.getValidator() == null) {

                if (defaultValidator != null) {
                    validatorMap.put(field, defaultValidator.newInstance());
                }

                continue;
            }
            validatorMap.put(field, mpColumn.getValidator().newInstance());

        }

        return validatorMap;

    }

    /**
     * 字段列Map转 Excel转换器Map
     *
     * @param columnMap 字段列Map
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static FieldExcelConvertMap columnMapToExcelConverterMap(Map<Field, MPColumn> columnMap, Class<? extends ExcelConverter> defaultConvert) throws IllegalAccessException, InstantiationException {

        FieldExcelConvertMap converterMap = new FieldExcelConvertMap();

        for (Field field : columnMap.keySet()) {

            MPColumn mpColumn = columnMap.get(field);

            if (mpColumn.getExcelConverter().equals(ExcelConverter.class) || mpColumn.getExcelConverter() == null) {
                mpColumn.setExcelConverter(defaultConvert);
            }

            converterMap.put(field, mpColumn.getExcelConverter().newInstance());

        }

        return converterMap;

    }

    /**
     * 工作表数组转Map
     *
     * @param sheets
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static MPSheetIndexMap sheetArrayToDataFilterMap(MPSheet[] sheets) throws IllegalAccessException, InstantiationException {
        if (sheets == null) {
            return new MPSheetIndexMap();
        }
        MPSheetIndexMap sheetMap = new MPSheetIndexMap();

        for (MPSheet mpSheet : sheets) {
            sheetMap.put(mpSheet.getIndex(), mpSheet);
        }
        return sheetMap;
    }

    /**
     * 字段Map转索引Map
     *
     * @param columnMap 字段Map值
     */
    public static IntegerStringMap columnMapToIndexMap(Map<Field, MPColumn> columnMap) {

        IntegerStringMap indexMap = new IntegerStringMap();

        for (Field field : columnMap.keySet()) {

            MPColumn mpColumn = columnMap.get(field);

            indexMap.put(mpColumn.getIndex(), field.getName());

        }

        return indexMap;
    }
}
